/**
 * @param {View} shell
 * @constructor
 */
function ToolbarMediator(shell)
{
	"use strict";

	/** @type {ToolbarMediator} */
	var _this = this;
	var _navigable = true;
	var $previous = $('#prevButton');
	var $zoom = $('#zoomButton');
	var $play = $('#playButton');
	var $next = $('#nextButton');
	var $max = $('#fullscreenButton');

	function init()
	{
		var $doc = $(document);

		register('#browseButton', shell.menu);
		register('#commentButton', shell.comment);
		register('#helpButton', shell.help);
		register('#aboutButton', shell.about);
		register('#cameraButton', shell.exif);
		register('#twitterButton', shell.twitter);
		register('#embedButton', shell.embed);
		register('#shareButton', shell.share);
		register('#giftButton', shell.quote);
		register('#mapButton', shell.map, true);

		$play.click(handler(shell.slideshow.toggle));
		$max.click(function() { $doc.fullScreen(true); });
		$next.click(handler(_this.next));
		$previous.click(handler(_this.previous));
		$zoom.click(handler(shell.photo.toggleZoom));
		$doc.on('fullscreenchange', function()
			{
				if ($doc.fullScreen()) { _this.disable($max); } else { _this.enable($max); }
			})
			.on('fullscreenerror', function()
			{
				_this.disable($max).attr('title', 'Your browser does not support full-screen mode');
			}
		);
	}

	/**
	 * @param {String} selector
	 * @param {BaseMediator|*} mediator
	 * @param {Boolean} [alignRight = false]
	 */
	function register(selector, mediator, alignRight)
	{
		var button = $(selector);

		mediator.button = selector;
		button.click(handler(mediator.toggle.bind(mediator)));
		mediator.align(button, alignRight);
	}

	/**
	 * Make conditional handler
	 * @param {Function} method
	 * @return {Function}
	 */
	function handler(method)
	{
		return function() {	if (_this.isEnabled(this)) { method(); } };
	}


// - Navigation ---------------------------------------------------------------

	/**
	 * Update next and previous buttons relative to photo
	 * @return {ToolbarMediator}
	 */
	this.updateNavigation = function()
	{
		if (_navigable)
		{
			enableIf($previous, Session.photo.previous);
			enableIf($next, Session.photo.next);
		}
		return _this;
	};

	/**
	 * @return {ToolbarMediator}
	 */
	this.disableNavigation = function()
	{
		_navigable = false;
		return _this.disable($previous).disable($next);
	};

	/**
	 * @return {ToolbarMediator}
	 */
	this.enableNavigation = function()
	{
		_navigable = true;
		return _this.enable($previous).enable($next);
	};

	/**
	 * @param {Event} [e]
	 * @return {ToolbarMediator}
	 */
	this.next = function(e)
	{
		return go($next, _this.nextPhoto, e);
	};

	/**
	 * @param {Event} [e]
	 * @return {ToolbarMediator}
	 */
	this.previous = function(e)
	{
		return go($previous, _this.previousPhoto, e);
	};

	/**
	 * Show next or previous photo if enabled
	 * @param {jQuery} button DOM element
	 * @param {Function} showPhoto Either nextPhoto() or previousPhoto()
	 * @param {Event} [e]
	 */
	function go(button, showPhoto, e)
	{
		if (_this.isEnabled(button))
		{
			shell.slideshow.active = false;
			shell.menu.hide();
			showPhoto();
		}
		return _this;
	}

	/**
	 * Update data element indicating if navigation is enabled
	 * @param {jQuery} button
	 * @param {Photo} photo
	 */
	function enableIf(button, photo)
	{
		if (photo != null) { _this.enable(button); } else { _this.disable(button); }
	}

	/**
	 * Highlight the next button
	 * @param {Boolean} [andGo = false] Whether to also navigate to the next photo
	 * @return {ToolbarMediator}
	 */
	this.highlightNext = function(andGo)
	{
		$next.bounceOpacity(500, 1, Enum.opacity.buttonNormal);
		return (andGo) ? _this.next() : _this;
	};

	/**
	 * Highlight the previous button
	 * @param {Boolean} [andGo = false] Whether to also navigate to the previous photo
	 * @return {ToolbarMediator}
	 */
	this.highlightPrevious = function(andGo)
	{
		$previous.bounceOpacity(500, 1, Enum.opacity.buttonNormal);
		return (andGo) ? _this.previous() : _this;
	};

	/**
	 * Shadow to implement loading next photo
	 */
	this.nextPhoto = function() { };

	/**
	 * Shadow to implement loading previous photo
	 */
	this.previousPhoto = function() { };

//- Button states -------------------------------------------------------------

	/**
	 * @param {Boolean} zoomed Whether display is zoomed
	 * @return {ToolbarMediator}
	 */
	this.toggleZoom = function(zoomed) { return toggle($zoom, zoomed); };

	/**
	 * @param {Boolean} playing Whether the slideshow is playing
	 * @return {ToolbarMediator}
	 */
	this.togglePlay = function(playing) { return toggle($play, playing) };

	/**
	 * For buttons with two icons, toggle between them
	 * @param {jQuery} button
	 * @param {Boolean} active
	 * @return {ToolbarMediator}
	 */
	function toggle(button, active)
	{
		var icons = button.children('i');
		var a, r;   // add / remove indices

		if (active) { a = 1; r = 0; } else { a = 0; r = 1; }

		icons.eq(r).css('display', 'none');
		icons.eq(a).css('display', 'inline-block');

		return _this;
	}

	/**
	 * @param {String|jQuery} button
	 * @return {ToolbarMediator}
	 */
	this.disable = function(button)
	{
		normalize(button).addClass('disabled');
		return _this;
	};

	/**
	 * @param {String|jQuery} button
	 * @return {ToolbarMediator}
	 */
	this.enable = function(button)
	{
		normalize(button).removeClass('disabled');
		return _this;
	};

	/**
	 * Whether button is enabled
	 * @param {String|jQuery|Element} button
	 * @return {Boolean}
	 */
	this.isEnabled = function(button)
	{
		return !normalize(button).hasClass('disabled');
	};

	/**
	 * @param {String|jQuery} button
	 * @param {Function} [method] Optional method to execute after selection
	 * @return {ToolbarMediator}
	 */
	this.select = function(button, method)
	{
		normalize(button)
			.addClass('selected')
			.find('i').removeClass('icon-white');

		if (method) { method(); }

		return _this;
	};

	/**
	 * @param {String|jQuery} button
	 * @return {ToolbarMediator}
	 */
	this.deselect = function(button)
	{
		normalize(button)
			.removeClass('selected')
			.find('i').addClass('icon-white');

		return _this;
	};

	/**
	 * @param {String|jQuery|Element} button
	 * @return jQuery
	 */
	function normalize(button)
	{
		return (button instanceof jQuery) ? button : $(button);
	}

	init();
}